<?php
/**
 * Zead
 *
 * LICENSE	
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/bsd-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to eu@marcelomx.com so we can send you a copy immediately.
 *
 * @category   Zead
 * @author     Marcelo Rodrigues Gonzaga <eu@marcelomx.com>
 * @copyright  Copyright (c) 2008 Marcelo Rodrigues Gonzaga
 * @link       http://code.google.com/p/zead 
 * @license    http://www.opensource.org/licenses/bsd-license.php     New BSD License
 *
 **/


/** @see  Zead_Player_Action_Helper_Abstract **/
require_once 'Zead/Player/Action/Helper/Abstract.php';

/** @see Zead_Metadata_HttpManager **/
require_once 'Zead/Manifest/Util.php';

/**
 * @category   Zead
 * @package    Zead_Player_Action
 * @package    Zead_Player_Action_Plugin
 * @copyright  Copyright (c) 2008 Marcelo Rodrigues Gonzaga 
 * @license    http://www.opensource.org/licenses/bsd-license.php     New BSD License 
 */

class Zead_Player_Action_Helper_Manifest extends Zead_Player_Action_Helper_Abstract
{
	/** @var Zead_Metadata_Manifest_Base */
	protected $_manifest = null;
	
	/** @var Zead_Metadata_Data_Resources_Resource  */
	protected $_current = null;
	
	/** @var Zead_PagesRange **/	
	protected $_currentHttpPages = null;
	
	/** @var Zead_PagesRange **/
	protected $_currentParentHttpPages = null;
	
	/** @var Zead_PagesRange **/
	protected $_currentStaticFiles = null;
	
	/** @var Zead_Metadata_Data_Resources_Resource */
	protected $_default = null;	
	
	/**
	 * Inicializando o helper
	 */
	public function init() 
	{
		// Recuperando o objeto 
		$this->_manifest = $this->getPlayer()->getParam('manifest');
		
		// Parses the default content
		//$this->_default = $this->_manifest->getDefault();
		
		// Parses the current content
		$this->_current = $this->_processCurrentFromContentsList($this->_manifest->getContents());
	}
	
	/**
	 * Retorna o título do metadados ou o título do recurso atual.
	 * @return string 
	 */
	public function getTitle()
	{		
		return $this->_manifest->getTitle();		
	}

	/**
	 * Verifica se há objeto corrente encontrado.
	 * @return bool
	 */
	public function hasCurrent() 
	{
		if ($this->_current != null) {
			return true;	
		}
		
		return false;
	}
	
	/**
	 * Trazendo o recurso atual acessado.
	 * @return Zead_Data_Resources_Resource
	 */
	public function getCurrent()
	{
		return $this->_current;
	}
	
	/**
	 * Returns the current content title
	 * @return string
	 */
	public function getCurrentTitle()
	{
		if (null == $this->_currentTitle) {
			if ($this->hasCurrent()) {
				$this->_currentTitle = $this->getCurrent()->getTitle();
			}
		}
		return $this->_currentTitle;
	}
	
	
	/**
	 * Returns the http pages to current content accessed.
	 * @return Zead_PagesRange
	 */
	public function getCurrentHttpPages()
	{
		if (null == $this->_currentHttpPages) {
			$this->_currentHttpPages = new Zead_PagesRange();
			
			if ($this->hasCurrent()) {
				$this->_currentHttpPages = Zead_Manifest_Util::getContentHttpPages($this->getCurrent(), $this->getPlayer()->credential['baseUri']); 
			}
		}
		
		return $this->_currentHttpPages;
	}
	
	/**
	 * Returns the parent contents http address
	 * @return Zead_PagesRange
	 */
	public function getCurrentParentHttpPages()
	{
		if (null == $this->_currentParentHttpPages) {
			$this->_currentParentHttpPages = new Zead_PagesRange();
			
			if ($this->hasCurrent()) {
				foreach ($this->getCurrent()->getParents(true) as $parent) {
					$parentPagesRange = Zead_Manifest_Util::getContentHttpPages($parent, $this->getPlayer()->credential['baseUri']);
					$this->_currentParentHttpPages->append($parentPagesRange->getPage(1)->url, $parent->getTitle(), $parent->getTitle());
				}
			}
		}
		
		return $this->_currentParentHttpPages;
	}
	
	/**
	 * Returns the parent contents http addres tree
	 * @return Zead_PagesRange
	 */
	public function	getCurrentParentHttpPagesTree()
	{
		if (null == $this->_currentParentHttpPagesTree) {
			$this->_currentParentHttpPagesTree = new Zead_PagesRange();
			if ($this->hasCurrent()) {
				$parentHttpPages = clone $this->getCurrentParentHttpPages();
				if ($parentHttpPages->count()) {
					$currentTitle = $this->getCurrent()->getTitle();
					$parentHttpPages->append($this->getRequest()->getScriptPath(), $currentTitle, $currentTitle);
					$this->_currentParentHttpPagesTree = $parentHttpPages;
				}
			}
		}
		return $this->_currentParentHttpPagesTree;
	}
	
	/**
	 * Returns the parent pages file to current content
	 * @return Zead_PagesRange
	 */
	public function getCurrentStaticFiles()
	{
		if (null == $this->_currentStaticFiles) {
			$this->_currentStaticFiles = new Zead_PagesRange();
			
			if ($this->hasCurrent()) {
				$this->_currentStaticFiles = Zead_Manifest_Util::getContentStaticFiles($this->getCurrent(), $this->getPlayer()->credential['basePath']);
			}
		}
		
		return $this->_currentStaticFiles;
	}
	
	/**
	 * Returns the table of contents as array
	 * @return array
	 */
	public function getTocList()
	{
		if (null == $this->_tocList) {
			$this->_minTitleLevel = 6;			
			$this->_tocList = $this->_createTocList($this->_manifest->getContentsList());
/*			var_dump($this->titleTags);
			var_dump($this->_minTitleLevel);	*/		
		}
		return $this->_tocList;
	}
	
	protected function _createTocList($contentsList)
	{
		$captureTitleTags = true;
		$tocList = new Zead_PagesRange();
		
		foreach ($contentsList as $content) {
			$httpPages = Zead_Manifest_Util::getContentHttpPages($content, $this->getPlayer()->credential['baseUri']);
			$firstPage = $httpPages->getPage(1);
			
			$tocEntry = new stdClass();
			$tocEntry->url = $firstPage->url;
			$tocEntry->title = $content->getTitle();
			$tocEntry->tocList = new Zead_PagesRange();			
			$tocEntry->tocList = $this->_createTocList($content->getContentsList());	
			$tocList[] = $tocEntry;			
			// Capture all title tags
			if ($captureTitleTags) {
				$files = Zead_Manifest_Util::getContentStaticFiles($content, $this->getPlayer()->credential['basePath']);
				foreach ($files as $key => $file) {
					//$url = $httpPages->getPage($key + 1)->url;
					if (file_exists($file->url)) {
						$html = new Zead_Html();
						$html->load($file->url);
						$this->_parseTitleTags($html->documentElement);
					}
				}
			}	
		}
		return $tocList;	
	}
	
	protected function _parseTitleTags($element)
	{
		foreach ($element->childNodes as $child) {
			if ($child->nodeType == 1 && $child->nodeValue != '') {
				if (preg_match("/^H([1-6])$/", strtoupper($child->nodeName), $match)) {
					$titleLevel = (int) $match[1];
					if ($titleLevel < $this->_minTitleLevel) {
						$this->_minTitleLevel = $titleLevel;
					}
					$o = new stdClass();
					$o->level = $titleLevel;
					$o->value = $child->nodeValue;
					$this->titleTags[] = $o;
				} else {
					$this->_parseTitleTags($child);
				}
			}
		}
	}
	
	protected $_organizeTitleTitleTagsFolding = array();
	
	protected function _organizeTitleTagsFolding($initLevel, $stack = array())
	{
		$list = array();
		
		foreach ($stack as $index => $object) {
			if ($object->level == $initLevel) {
			}
		}
	}
	
	/**
	 * Returns the contents list as menu list
	 * @return Zead_PagesRange
	 */
	public function getMenuList()
	{
		if (null == $this->_menuList) {
				$this->_menuList = $this->_createMenuList($this->_manifest->getContentsList());
		}
		return $this->_menuList;	
		
	}	
	
	public function _createMenuList($contentsList)
	{
		$menuList = new Zead_PagesRange();
		
		foreach ($contentsList as $content) {
			$httpPages = Zead_Manifest_Util::getContentHttpPages($content, $this->getPlayer()->credential['baseUri']);
			$firstPage = $httpPages->getPage(1);
			
			$menuEntry = new stdClass();
			$menuEntry->url = $firstPage->url;
			$menuEntry->title = $content->getTitle();
			$menuEntry->label = $content->getAttr('label');
			$menuEntry->menuList = $this->_createMenuList($content->getContentsList());	
			$menuList[] = $menuEntry;			
		}
		return $menuList;		
	}

	
	/**
	 * Retorna o recurso padrão registrado no metadados.
	 * @return Zead_Data_Resources_Resource 
	 */
	public function getDefault()
	{
		return $this->_default;
	}
	
	
	/**
	 * Returns the http address for default content
	 * @return string
	 */
	public function getDefaultPage()
	{
		if (null == $this->_defaultPage) {
			$pagesRange = Zead_Manifest_Util::getContentHttpPages(
				$this->getDefault(), 
				$this->getPlayer()->credential['baseUri'],
				$this->getRequest()->getBaseQuery());
			// get the first page
			$this->_defaultPage = $pagesRange->getPage(1)->url;
		}
		
		return $this->_defaultPage;
	}
	
	/**
	 * Returns the manifest object
	 * @return Zead_Manifest_Object
	 */	
	public function getObject()
	{
		return $this->_manifest;
	}
	
	/**
	 * Process and find a current content from contents list
	 * @param Zead_Manifest_ContentsList $contentsList
	 */
	public function _processCurrentFromContentsList($contentsList)
	{			
		$current = null;
		
		foreach ($contentsList->getChildren() as $content) {
			$currentHttpPages = Zead_Manifest_Util::getContentHttpPages($content, $this->getPlayer()->credential['baseUri']);
			
			// Search in content pages			
			if ($this->_isCurrentRequestPage($currentHttpPages)) {
				$current = $content;
				break;
			} else if (($current = $this->_processCurrentFromContentsList($content))) {
				break;
			}
		}
		
		return $current;
	}
	
	/**
	 * Process pages and compare with current request page
	 * @param  Zead_PagesRange
	 * @return bool
	 */
	protected function _isCurrentRequestPage($pages)
	{
		$script = $this->getRequest()->getScriptName();
		
		foreach ($pages as $page) {
			if ($page->url == $script) 
				return true;
		}
		
		return false;
	}
}

